<?php

namespace app\common\library\notice;

use Flc\Dysms\Client;
use Flc\Dysms\Request\SendSms;

/**
 * 发送短信
 *
 * @author LCY <409028735@qq.com>
 */
class Sms
{
    protected static $config = [
        'sms_key_id' => 'LTAI5tGH2pXk417yzhBPy9FS',
        'sms_key_secret' => '5vCStDzAUHbitrPPSCz3HUJoxbkTWn',
        'sms_sign' => '乐之寓',
        'templates' => [
            'login' => 'SMS_274850633', //登录验证码模板
            'forget' => 'SMS_274850633', //找回密码验证码模板
            'change' => 'SMS_274850633', //换绑手机号验证码模板
            'notice' => '', //招商审核通知的模板
        ]
    ];

    /**
     * 发送短信
     *
     * @param string $scene
     * @param string $mobile
     * @param array $template_params
     * @return true|string true：表示发送成功，string：表示发送失败的提示
     */
    public static function send($scene, $mobile, $template_params = [])
    {
        self::setConfig();
        //检测手机号
        if (true !== $res = self::checkMobile($scene, $mobile)) {
            return $res;
        }

        $res = self::sendSms($mobile, self::$config['templates'][$scene], $template_params);
        if ('ok' == strtolower($res->Code)) {
            return true;
        } else {
            trace($mobile . '：发送短信失败：' . $res->Message, 'error');
            return '发送失败';
        }
    }

    /**
     * 发送短信验证码
     *
     * @param string $scene 场景
     * @param string $mobile 手机号
     * @param integer $expire 有效期，单位分钟
     * @return true|string true：表示发送成功，string：表示发送失败的提示
     */
    public static function sendCode($scene, $mobile, $expire = 5)
    {
        try {
            self::setConfig();

            //检测手机号
            if (true !== $res = self::checkMobile($scene, $mobile)) {
                return $res;
            }
            $key = self::buildCodeKey($scene, $mobile);

            $code = mt_rand(10000, 99999); //随机产生短信验证码
            $template_params = [
                'code' => $code,
            ];

            //缓存数据
            $cache_data = json_encode(['code' => $code, 'time' => time()]);
            cache($key, $cache_data, $expire * 60);

            $res = self::sendSms($mobile, self::$config['templates'][$scene], $template_params);
            if ('ok' == strtolower($res->Code)) {
                return true;
            } else {
                trace($mobile . '：发送短信验证码失败：' . $res->Message, 'error');
                return '发送失败';
            }
        } catch (\Exception $e) {
            recordExceptionInfo($e);
            return '发送失败';
        }
    }

    /**
     * 验证短信验证码
     *
     * @param string $scene 场景
     * @param string $mobile 手机号
     * @return bool true：验证通过 否则验证失败
     */
    public static function checkCode($scene, $mobile, $code = '')
    {
        $key = self::buildCodeKey($scene, $mobile);
        $cache_data = cache($key);
        if (!empty($cache_data)) {
            $cache_data = json_decode($cache_data, true);
            if ($code != $cache_data['code']) {
                return '验证码有误';
            }

            //验证通过后，马上失效
            cache($key, null);
            return true;
        } else {
            return '验证码不存在或已过期';
        }
    }

    /**
     * 构建短信验证码的key名称
     *
     * @param string $scene
     * @param string $mobile
     * @return string
     */
    protected static function buildCodeKey($scene, $mobile)
    {
        return 'smscode_' . $scene . '_' . $mobile;
    }

    /**
     * 验证短信验证码
     *
     * @param string $scene 场景
     * @param string $mobile 手机号
     * @return bool true：验证通过 否则验证失败
     */
    protected static function checkMobile($scene, $mobile)
    {
        if (!array_key_exists($scene, self::$config['templates'])) {
            return '场景值不支持';
        }

        //检测手机号的格式
        if (!preg_match('/^1[3-9]\d{9}$/', $mobile)) {
            return '手机号码有误';
        }

        //发送频繁的检测
        $key = self::buildCodeKey($scene, $mobile);
        $cache_data = cache($key);
        if (!empty($cache_data)) {
            $cache_data = json_decode($cache_data, true);
            if ($cache_data['time'] + 50 > time()) {
                return '发送过于频繁';
            }
        }

        //根据场景值，进一步检测手机号码（查询数据库判断是否存在）

        return true;
    }

    /**
     * 设置配置
     *
     * @param [type] $config
     * @return void
     */
    protected static function setConfig()
    {
        $config = config('sms.');
        if (!empty($config)) {
            self::$config = array_merge(self::$config, $config);
        }
    }



    /**
     * 发送短信
     * @param string $mobiles  手机号，多个用英文逗号分隔
     * @param string $sign     短信签名
     * @param string $template  模板ID
     * @param array $template_params  模板参数
     * Author: LCY<409028735@qq.com>
     * Time: 2020/12/23 10:40
     * Note:
     */
    protected static function sendSms($mobiles = '', $template = '', $template_params = [])
    {
        $config = [
            'accessKeyId'    => self::$config['sms_key_id'],
            'accessKeySecret' => self::$config['sms_key_secret'],
        ];

        $client  = new Client($config);
        $sendSms = new SendSms;
        $sendSms->setPhoneNumbers($mobiles);
        $sendSms->setSignName(self::$config['sms_sign']);
        $sendSms->setTemplateCode($template);
        $sendSms->setTemplateParam($template_params);
        $sendSms->setOutId('verify');
        return $client->execute($sendSms);
    }
}
